package cn.gjxblog.expression;

import cn.gjxblog.common.Person;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.springframework.context.expression.BeanExpressionContextAccessor;
import org.springframework.context.expression.EnvironmentAccessor;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.expression.*;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

@RunWith(JUnit4.class)
public class TestPropertyAccessor {


    /**
     * 因为我们指定的PropertyAccessor中，没有一个能够处理Person.class这个类型。
     * 然而最终会交给ReflectivePropertyAccessor处理，而它的canRead()是返回false的
     * （Person类因为它既没有person方法，也没有person字段所以肯定返回false啊），所以就抛出异常了~
     */
    @Test
    public void test1(){
        String expressionStr = "person";
        ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression(expressionStr);

        // 设置targetType为Person类型
        StandardEvaluationContext context = new StandardEvaluationContext(new Person("fsx", 18));
        context.addPropertyAccessor(new BeanExpressionContextAccessor());

        System.out.println(expression.getValue(context));

    }

    /**
     * 自定义PropertyAccessor扩展SpEL的功能
     */
    @Test
    public void test2(){
        String expressionStr = "person2";
        ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression(expressionStr);

        // 设置targetType为Person类型
        StandardEvaluationContext context = new StandardEvaluationContext(new Person("fsx", 18));
        // 通过自定义一个处理器，让能从Person类里解析person这个Name引用~
        context.addPropertyAccessor(new PropertyAccessor() {
            @Override
            public Class<?>[] getSpecificTargetClasses() {
                return new Class[]{Person.class};
            }

            @Override
            public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
                if(target instanceof Person){
                    return true;
                }
                return false;
            }

            @Override
            public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
                Person person = (Person) target;
                return new TypedValue(person.getName());
            }

            @Override
            public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
                return false;
            }

            @Override
            public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {

            }
        });

        System.out.println(expression.getValue(context));
    }

    /**
     * 演示其它PropertyAccessor生效
     */
    @Test
    public void test3(){
        String expressionStr = "['user.home']";
        ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression(expressionStr);

        // 设置targetType为StandardEnvironment类型,以及属性访问器EnvironmentAccessor
        StandardEvaluationContext context = new StandardEvaluationContext(new StandardEnvironment());
        context.addPropertyAccessor(new EnvironmentAccessor());

        System.out.println(expression.getValue(context));

    }
}
